/********************************************************************
//	Character.cpp
//	2012 12 14 - J. A. Cripe jacripe@gmail.com http://wiseeyesent.com
//
//	Character Class Definition File
//	Includes:
//			- Class/Function Definitions
//
********************************************************************/

#include "Character.h"

Character::Character(float x, float y, CHAR_TYPE c) {
	id = rand() % (int)time(NULL);
	defaultX = posX = x; defaultY = posY = y;
	velX = velY = 0;
	charType = c;
	mKey = false;
	isStanding = true;
	nKeys = 0;
	
	Sprite s; RECT r;
	if(c == cPLAYER)
		r.left = 0; 
	else if(c == cENEMY)
		r.left = SPRITE_SIZE * NUM_DIRS;
	else //c == cALLY
		r.left = SPRITE_SIZE * (NUM_DIRS * 2);
	r.right = r.left + SPRITE_SIZE;
	r.top = 0;
	r.right = r.top + SPRITE_SIZE;

	s.sourceRect = r;
	s.cFrame = 0;
	s.nFrames = 4;
	s.pX = x;
	s.pY = y;
	s.vX = velX;
	s.vY = velY;
	//sprite = s;
	
	next = NULL;
}

void Character::setPos(float x, float y) {
	posX = x;
	posY = y;
}

void Character::getPos(float* x, float* y) {
	*x = posX;
	*y = posY;
}

void Character::setVel(float x, float y) {
	velX = x;
	velY = y;
}
void Character::getVel(float* x, float* y) {
	*x = velX;
	*y = velY;
}

bool Character::standing(void) {
	return isStanding;
}

void Character::crouch(void) {
	isStanding = false;
	this->sprite.sourceRect.left += SPRITE_SIZE;
	this->sprite.sourceRect.right += SPRITE_SIZE;
	//LOG << "Character::crouch @ " << printTime() << "\tPlayer crouches!\n";
	//LOG << "\tsrcRec [" << this->getSourceRect().top << ". " << this->getSourceRect().bottom
		//<< " : " << this->getSourceRect().left << ". " << this->getSourceRect().right << "]\n";
}

void Character::stand(void) { 
	isStanding = true;
	RECT temp = sprite.sourceRect;
	temp.left -= SPRITE_SIZE;
	temp.right -= SPRITE_SIZE;
	sprite.sourceRect = temp;
	//LOG << "Character::stand @ " << printTime() << "\tPlayer stands!\n";
	//LOG << "\tsrcRec [" << this->getSourceRect().top << ". " << this->getSourceRect().bottom
		//<< " : " << this->getSourceRect().left << ". " << this->getSourceRect().right << "]\n";
}

void Character::move(void) {
	//if(*log == NULL)
	//	log = &GFX_LOG;
	
	posX += velX;// * timerRate;
	posY += velY;// * timerRate;
}

void Character::setSprite(Sprite s) { sprite = s; }
Sprite Character::getSprite(void) { return sprite; }

void Character::cycleFrame(void) {
	//*log << "Character::cycleFrame() START @ " << printTime();
	//*log << "\tcharType: " << charType << "\n";

	int spriteCol = 0,
		spriteRow = 0; // Used for determining location of frame in SpriteSheet

	spriteCol += (charType * NUM_DIRS);

	updateDir(); //Make sure direction is properly set
	//*log << "\tdir: " << dir << ", Vel ( " << velX << ", " << velY << " )\n";
	spriteCol += dir;
	if(velX != 0 || velY != 0) { // If moving
		sprite.cFrame = sprite.cFrame + 1;
		if(sprite.cFrame >= sprite.nFrames)
			sprite.cFrame = 0;
	}
	//*log << "\tcFrame: " << sprite.cFrame << ", nFrames: " << sprite.nFrames << "\n";
	spriteRow += sprite.cFrame;
	//*log << "\tspriteCol: " << spriteCol << ", spriteRow: " << spriteRow << "\n";

	RECT tmp;
	tmp.left = spriteCol * SPRITE_SIZE; tmp.right = tmp.left + SPRITE_SIZE;
	tmp.top = spriteRow * SPRITE_SIZE; tmp.bottom = tmp.top + SPRITE_SIZE;
	sprite.sourceRect = tmp;
	//*log << "\tsourceRect [ " << tmp.left << ", " << tmp.right
	//	 << ", " << tmp.top << ", " << tmp.bottom << "\n";
	//*log << "Character::cycleFrame STOP @ " << printTime();
}

void Character::updateDir(void) {
//	*log << "Character::updateDir() START @ " << printTime();
//	*log << "\tdir: " << dir << "\n";
//	*log << "\tVel ( " << velX << ", " << velY << ")\n";
	if(velY < 0)
		dir = N;
	else if(velY > 0)
		dir = S;
	else { //velY == 0
		if(velX > 0)
			dir = E;
		else if(velX < 0)
			dir = W;
		//else
		//	dir = S; //No Movement, Assume direction is south
	}

	if(dir < 0 || dir > 4)
		dir = S;
//	*log << "\tdir: " << dir << "\n";
//	*log << "Character::updateDir() STOP @ " << printTime();
}

bool Character::checkCollision(float x, float y, OBJ_TYPE obj) {
	if(*log == NULL)
		log = &GFX_LOG;

	//JC Added no-clipping/god-mode cheat
	if(cheater)
		if(this->charType == cPLAYER)
			if(obj != oALLY && obj != oKEY && obj != oLDOOR)
				return false;

	//JJ Test if character is colliding with door
	float	px, py, // Character Center
			ox, oy; // Object Center

	// Calculate Character Center
	px = posX + (SPRITE_SIZE / 2);
	py = posY + (SPRITE_SIZE / 2);

	// Calculate Object Center
	ox = x + (SPRITE_SIZE / 2);
	oy = y + (SPRITE_SIZE / 2);

	float difX = px - ox;
	float difY = py - oy;

	//JC Collision Detection Fudge Factor
	if(charType == cPLAYER && obj != oALLY) {
		difX = (float)(difX * 1.2);
		difY = (float)(difY * 1.2);
	}
	//if(obj == oWALL) {
	//	difX = (float)(difX * 1.1);
	//	difY = (float)(difY * 1.1);
	//}

	if(abs(difX) <= SPRITE_SIZE && abs(difY) <= SPRITE_SIZE) {
		/**log << "Character::checkCollision() @ " << printTime()
			 << "COLLISION!\tCOLLISION!\tCOLLISION!\n"
			 << "P(" << px << "," << py << "); O(" << ox << "," << oy << ")\n"
			 << "DIF(" << difX << "," << difY << "); "
			 << "CHAR_TYPE: " << charType << "OBJ_TYPE: " << obj << "\n";	*/

		if(abs(difX) < abs(difY)) { // Vertical Collision
			velY *= -1;
			if(charType == cPLAYER) {
				posY = (difY > 0) ? ++posY : --posY;
				velY = 0;
			}
		} else if(abs(difX) > abs(difY)) { // Horizontal Collision
			velX *= -1;
			if(charType == cPLAYER) {
				posX = (difX > 0) ? ++posX : --posX;
				velX = 0;
			}
		} else { // Corner Collision
			// No Additional Code appears necessary currently
		}

		return true;
	}

	return false;
}